package compilers.AST.statement;

import java.util.Iterator;

import compilers.AST.Node;
import compilers.AST.expression.Expression;
import compilers.AST.types.TypeSpecifier;
import compilers.compiler.PGenerator;
import compilers.exceptions.SemanticalException;
import compilers.symbolTable.SymbolTableElement;
import compilers.symbolTable.SymbolTableFunctionElement;
import compilers.symbolTable.SymbolTableScope;
import compilers.symbolTable.SymbolTableVariableElement;

public class ReturnStatement extends Statement {

	private Expression fExpression;
	
	public ReturnStatement() {	}
	
	public ReturnStatement(int lineNr) {
		super(lineNr);
	}
	
	public void print(int identLevel) {
		println(identLevel, "ReturnStatement");
		fExpression.print(identLevel+1);
	}
	
	public void setExpression(Expression expression) {
		fExpression = expression;
	}
	
	public int getResultType(SymbolTableScope currentScope) {
		return fExpression.getResultType(currentScope);
	}
	
	public void checkSemantics(SymbolTableScope currentScope) throws SemanticalException {
		boolean funFound = false;
		SymbolTableScope tmpScope = currentScope;
		Node scopeNode = tmpScope.getScopeNode();
		while(scopeNode != null) {
			if(scopeNode instanceof FunctionDefinitionStatement) {
				funFound = true;
			}
			tmpScope = tmpScope.getParent();
			scopeNode = tmpScope.getScopeNode();
		}
		if(!funFound) {
			throw new SemanticalException("Return-statement not allowed in this context.", getLine());
		}
		fExpression.checkSemantics(currentScope);
	}
	
	public void generatePcode(PGenerator pGen, SymbolTableScope currentScope) {
		//Generate code for the expression so that the result is on top of the stack
		fExpression.generatePcode(pGen, currentScope);
		//TODO: change str depth
		pGen.str(TypeSpecifier.getPType(fExpression.getResultType(currentScope)), 0, 0);
		pGen.retf();
	}
}
